expand-grammar expands the tree on a given recursion level, returning those elements that have no further definitions. With combination of def-grammar this function ables to define song structures of any complexity level.
(def-grammar 'structure
fugue (intro variations coda) ; add cadenza
variations (part1 part2 part3 part4)
variations (part3 part2 part1 part4)
)
You have many options on defining the grammars. In the above is shown the possibility to use non-deterministic grammars, which can expand in different ways.
(expand-grammar fugue 2 'structure)
-->(intro part1 part2 part3 part4 coda)
(expand-grammar fugue 2 'structure)
--> (intro part3 part2 part1 part4 coda)
The definitions can be any symbols, and the results are applicable to all compositional parameters, directly or with the aid of conversions functions. When defining the song structure, use expand-grammar in combination with realize-class to define instruments.
(realize-class :all
instr1 (expand-grammar fugue 2 'structure)
instr2 (expand-grammar fugue 2 'structure)
instr3 (expand-grammar fugue 2 'structure)
instr4 (expand-grammar fugue 2 'structure)
)
Example
Let's make a grammar tree.
(def-grammar 'structure
fugue (intro variations coda)
variations (part1 part2 part3 part4)
)
What does expand-grammar do? It walks through the given tree and returns the nodes that contain no further nodes. If you imagine an ordinary tree, then expand-grammar returns all the leaves. Using the above tree we get:
(expand-grammar fugue 2 'structure)
--> (intro part1 part2 part3 part4 coda)
Notice how the variations node is expanded to part1 ... part4. Intro and code contain no further nodes, and are thus returned as is.
How is the level of expand-grammar controlled? Let's make a recursive grammar. Here variations consists of part1, part2, itself, part3 and part4. Looks tricky and not certainly stuff ordinary composers are using, but possible.
(def-grammar 'structure
fugue (intro variations coda)
variations (part1 part2 variations part3 part4)
)
Now, what happens when this tree is expanded? Let's try it on the same level as in previous example.
(expand-grammar fugue 2 'structure)
--> (intro part1 part2 part3 part4 coda)
We'll get the same output. On level 2 the variations is not expanded further. Let's try level 3.
Realize-class makes instrument bindings. If you want to bind all class definitions of section a to instr1 you'll write it this way:
(realize-class :all
instr1 '(a)
)
If you want to realize also other sections you can just extend the list of sections. Here you bind section a, section b, and again section a and b to instr1. When you now compile-instrument instr1 it will play sections a b a b.
(realize-class :all
instr1 '(a b a b)
)
Since expand-grammar returns lists of sections, you can replace the manually written list in the above example
You can now realize the classes by expand-grammar function. It will now return the sections and realize-class will make the instrument bindings accordingly.
(realize-class :all
instr1 (expand-grammar fugue 2 'structure)
)
So, actually the above makes this:
(realize-class :all
instr1 '(intro part1 part2 part3 part4 coda)
)
And then you can play your instrument
(compile-instrument "ccl;output:" "my song"
instr1
)
How does realize-class and expand-grammar relate to play-file?
Play-file does them automatically. Notice that def-orchestra makes similar tree grammars, but it is only used for inheritation, not expansion.
(def-orchestra 'orchestra
all-instruments (piano synth)
piano (left-hand right-hand)
)
(def-grammar 'structure
fugue (intro variations coda)
variations (part1 part2 part3 part4)
)
Then you play all-instruments in fugue section structure.
(play-file "my song"
all-instruments '(fugue)
)
Using recursive section structures
If so, you cannot use play-file. You have to write the above example with realize-class and expand-grammar. Why? Play-file cannot handle recursion.
(def-orchestra 'orchestra
all-instruments (piano synth)
piano (left-hand right-hand)
)
(def-grammar 'structure
fugue (intro variations coda)
variations (part1 part2 variations part3 part4)
)
(realize-class :all
instr1 (expand-grammar fugue 4 'structure)
)
(compile-instrument "ccl;output:" "my song"
instr1
)
This ends up playing instr1 to midi file with section structure